const PENDING = 'pending'; //等待
const FULFILLED = 'fufilled'; //成功
const REJECTED = 'rejected'; //失败
class MyPromise { //我的promise
	constructor(exectuor) {
		//exectuor就是new时候（）=>{}的执行器，因为执行器时立即执行的，所以在下面立即调用一下
		//resolve和reject为执行器的两个参数
		//trycatch判断执行器是否异常异常调用catch将异常方法返回
		try {
			exectuor(this.resolve, this.reject)
		} catch (err) {
			this.reject(err)
		}
	}

	status = PENDING; // 状态值
	value = undefined; //保存成功后的数值
	reason = undefined; //保存失败后的原因
	successCallback = []; //成功的回调数组
	failCallback = []; //失败的回调的数组

	//定义成箭头函数是为了让this指向MyPromise，否在指向window或者undefined
	resolve = (value) => {
		//因为状态是单向不可逆的，所以判断一下状态值
		if (this.status !== PENDING) return;
		//状态变为成功  
		this.status = FULFILLED;
		//保存成功后的数值
		this.value = value;
		//判断成功回调是否存在
		//this.successCallback && this.successCallback(this.value)

		while (this.successCallback.length) let result = this.successCallback.shift()()
	}

	reject = (reason) => {
		//因为状态是单向不可逆的，所以判断一下状态值
		if (this.status !== PENDING) return;
		//状态变为失败      
		this.status = REJECTED;
		//保存失败的原因
		this.reason = reason;
		//判断失败回调是否存在
		//this.failCallback && this.failCallback(this.value)
		//循环调用回已经储存的回调函数
		while (this.failCallback.length) this.failCallback.shift()()
	}
	//then判断内部事件状态，被定义在原型对象中，成功调用fulfilledcallback，失败回调rejectedcallback
	then(fulfilledcallback, rejectedcallback) {
		//如果then中未定义回调函数，那么手动传建一个，将数值向下传递
		fulfilledcallback = fulfilledcallback ? fulfilledcallback = value => value
		rejectedcallback = rejectedcallback ? rejectedcallback = reason => {
			throw reason
		}
		//链式调用then后面给是promise对象
		let promise2 = new MyPromise((resolve, reject) => {
			if (this.status === FULFILLED) {
				//then方法回调如果执行时报错，要调用下一个promise回调函数传出去，以便下一个then解析
				try {
					setTimeout(() => {
						//判断x的值是普通值还是promise对象
						//如果是普通值直接调用resolve
						//如果是promise对象查看返回的结果决定调用resolve还是reject
						let x = fulfilledcallback(this.value);
						//为了避免调用自己报错，使用setTimeout变成宏任务，以便传入promise2方便判断								
						resolvePromise(promise2, x, resolve, reject)
					}, 0)
				} catch (err) {
					reject(err)
				}

			} else if (this.status === REJECTED) {
				try {
					setTimeout(() => {
						//判断x的值是普通值还是promise对象
						//如果是普通值直接调用resolve
						//如果是promise对象查看返回的结果决定调用resolve还是reject
						let x = rejectedcallback(this.reason);
						//为了避免调用自己报错，使用setTimeout变成宏任务，以便传入promise2方便判断								
						resolvePromise(promise2, x, resolve, reject)
					}, 0)
				} catch (err) {
					reject(err)
				}
			} else {
				//将成功回调和失败回调存储起来					
				this.successCallback.push(() => {
					fulfilledcallback()
					try {
						setTimeout(() => {
							//判断x的值是普通值还是promise对象
							//如果是普通值直接调用resolve
							//如果是promise对象查看返回的结果决定调用resolve还是reject
							let x = fulfilledcallback(this.value);
							//为了避免调用自己报错，使用setTimeout变成宏任务，以便传入promise2方便判断									
							resolvePromise(promise2, x, resolve, reject)
						}, 0)
					} catch (err) {
						reject(err)
					}
				})
				this.failCallback.push(() => {
					try {
						setTimeout(() => {
							//判断x的值是普通值还是promise对象
							//如果是普通值直接调用resolve
							//如果是promise对象查看返回的结果决定调用resolve还是reject
							let x = rejectedcallback(this.reason);
							//为了避免调用自己报错，使用setTimeout变成宏任务，以便传入promise2方便判断								
							resolvePromise(promise2, x, resolve, reject)
						}, 0)
					} catch (err) {
						reject(err)
					}
				})
			}
		});
		return promise2;
	}
	finally(callback) {
		return this.then(value => {
			callback();
			return MyPromise.resolve(callback()).then(() => value)
		}, reason => {
			return MyPromise.resolve(callback()).then(() => {
				throw reason
			})
		})
	} catch (failCallback) {
		return this.then(undefined, failCallback)
	}
	static all(arr) {
		let result = [];
		let index = 0;
		return new MyPromise((resolve, reject) => {
			function addData(key, value) {
				//for循环是同步执行的，对于参与度的异步操作需要等待期执行完毕用index判断
				result[key] = value;
				index++;
				if (index == arr.length) {
					resolve(result);
				}
			}
			for (let i = 0; i < arr.length; i++) {
				let current = arr[i];
				//判断all当前的参数是否是普通值还是MyPromise对象
				if (current instanceof MyPromise) {
					//promise
					current.then(value => addData(i, value), reason => reject(reason))
				} else {
					//普通值
					addData(i, arr[i])
				}
			}

		})
	}
	static resolve(value) {
		//静态函数resolve判断传入的数值类型，如果为普通值包装成new MyPromise 如果是promise对象直接返回
		if (value instanceof MyPromise) {
			return value;
		} else {
			return new MyPromise(resolve => resolve(value))
		}
	}

}
//解读promise状态的公共函数，成功或者失败传递给下一个then进行解析
function resolvePromise(promise2, x, resolve, reject) {
	if (promise2 == x) {
		reject("类型错误");
	}
	if (x instanceof MyPromise) {
		x.then(resolve, reject)
	} else {
		resolve(x);
	}
}
